/*
 * Universidad Nacional de Colombia - Sede Bogotá *
 *
 *      David Montaño - damontanofe@unal.edu.co
 *      Laura Moreno - lvmorenoc@unal.edu.co
 *      Christian Rodriguez - carodriguezb@unal.edu.co
 *
 * Código liberado bajo licencia Creative Commons 3.0
 * http://creativecommons.org/licenses/by-nc-sa/3.0/
 */
package org.cripto.gui.hmriv;

import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.UIManager;
import javax.swing.JFileChooser;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import java.util.Random;
import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.Vector;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.filechooser.FileNameExtensionFilter;
import org.cripto.image.ImageProcessing;
import org.cripto.cipher.image.HillMRIVCipher;
import org.cripto.utils.ArraysUtils;
import org.cripto.utils.jama.Matrix;

/**
 *
 * @author damontanofe,lvmorenoc,carodriguezb
 */
public class guiHillMRIV extends javax.swing.JFrame {

    /** Creates new form guiHillMRIV */
    public guiHillMRIV() {
        initComponents();
        this.setIconImage(new ImageIcon(getClass().getResource("/org/cripto/gui/hmriv/images/icon.png")).getImage());
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        panelClave = new javax.swing.JLayeredPane();
        textoTamanoclave = new javax.swing.JLabel();
        cajaRutaArchivo = new javax.swing.JTextField();
        tamanoClaveHillMRIV = new javax.swing.JTextField();
        textoRuta = new javax.swing.JLabel();
        botonCargarClave = new javax.swing.JButton();
        botonVisualizarClave = new javax.swing.JButton();
        botonGenerarClave = new javax.swing.JButton();
        panelAcciones = new javax.swing.JLayeredPane();
        botonCifrarHill = new javax.swing.JButton();
        botonCifrarHillMRIV = new javax.swing.JButton();
        panelimagenes = new javax.swing.JLayeredPane();
        textoImagen = new javax.swing.JLabel();
        textoImagenHill = new javax.swing.JLabel();
        textoImagenHillMRIV = new javax.swing.JLabel();
        botonLimpiarImagenHillMRIV = new javax.swing.JButton();
        botonGuardarImagenHillMRIV = new javax.swing.JButton();
        cargarImagenHillMRIV = new javax.swing.JButton();
        cargarImagenHill = new javax.swing.JButton();
        botonLimpiarImagenHill = new javax.swing.JButton();
        botonGuardarImagenHill = new javax.swing.JButton();
        botonLimpiarImagen = new javax.swing.JButton();
        cargarImagen = new javax.swing.JButton();
        botonGuardarImagen = new javax.swing.JButton();
        botonAbrirImagen = new javax.swing.JButton();
        botonSalir = new javax.swing.JButton();
        botonAcercaDe = new javax.swing.JButton();
        jLabel1 = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("HillMRIV");
        setMinimumSize(new java.awt.Dimension(632, 0));
        setResizable(false);

        panelClave.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Clave", javax.swing.border.TitledBorder.LEFT, javax.swing.border.TitledBorder.TOP));

        textoTamanoclave.setText("Tamaño de la clave");
        textoTamanoclave.setBounds(20, 32, 117, 14);
        panelClave.add(textoTamanoclave, javax.swing.JLayeredPane.DEFAULT_LAYER);

        cajaRutaArchivo.setEditable(false);
        cajaRutaArchivo.setBounds(152, 67, 230, 20);
        panelClave.add(cajaRutaArchivo, javax.swing.JLayeredPane.DEFAULT_LAYER);

        tamanoClaveHillMRIV.setHorizontalAlignment(javax.swing.JTextField.CENTER);
        tamanoClaveHillMRIV.setBounds(150, 28, 40, 20);
        panelClave.add(tamanoClaveHillMRIV, javax.swing.JLayeredPane.DEFAULT_LAYER);

        textoRuta.setText("Ruta de la clave");
        textoRuta.setBounds(20, 70, 120, 14);
        panelClave.add(textoRuta, javax.swing.JLayeredPane.DEFAULT_LAYER);

        botonCargarClave.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/cripto/gui/hmriv/images/cargar.png"))); // NOI18N
        botonCargarClave.setText("Cargar clave");
        botonCargarClave.setToolTipText("Cargar clave");
        botonCargarClave.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                botonCargarClaveActionPerformed(evt);
            }
        });
        botonCargarClave.setBounds(206, 100, 176, 30);
        panelClave.add(botonCargarClave, javax.swing.JLayeredPane.DEFAULT_LAYER);

        botonVisualizarClave.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/cripto/gui/hmriv/images/ver.png"))); // NOI18N
        botonVisualizarClave.setText("Visualizar clave");
        botonVisualizarClave.setToolTipText("Visualizar clave");
        botonVisualizarClave.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                botonVisualizarClaveActionPerformed(evt);
            }
        });
        botonVisualizarClave.setBounds(15, 100, 176, 30);
        panelClave.add(botonVisualizarClave, javax.swing.JLayeredPane.DEFAULT_LAYER);

        botonGenerarClave.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/cripto/gui/hmriv/images/clave.png"))); // NOI18N
        botonGenerarClave.setText("Generar y guardar clave");
        botonGenerarClave.setToolTipText("Generar y guardar clave");
        botonGenerarClave.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                botonGenerarClaveActionPerformed(evt);
            }
        });
        botonGenerarClave.setBounds(206, 23, 176, 30);
        panelClave.add(botonGenerarClave, javax.swing.JLayeredPane.DEFAULT_LAYER);

        panelAcciones.setBorder(javax.swing.BorderFactory.createTitledBorder("Acciones"));

        botonCifrarHill.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/cripto/gui/hmriv/images/cifrar.png"))); // NOI18N
        botonCifrarHill.setText("Cifrar usando Hill");
        botonCifrarHill.setToolTipText("Cifrar usando Hill");
        botonCifrarHill.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        botonCifrarHill.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                botonCifrarHillActionPerformed(evt);
            }
        });
        botonCifrarHill.setBounds(15, 30, 190, 40);
        panelAcciones.add(botonCifrarHill, javax.swing.JLayeredPane.DEFAULT_LAYER);

        botonCifrarHillMRIV.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/cripto/gui/hmriv/images/cifrarAlt.png"))); // NOI18N
        botonCifrarHillMRIV.setText("Cifrar usando HillMRIV");
        botonCifrarHillMRIV.setToolTipText("Cifrar usando HillMRIV");
        botonCifrarHillMRIV.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
        botonCifrarHillMRIV.setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
        botonCifrarHillMRIV.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                botonCifrarHillMRIVActionPerformed(evt);
            }
        });
        botonCifrarHillMRIV.setBounds(15, 85, 190, 40);
        panelAcciones.add(botonCifrarHillMRIV, javax.swing.JLayeredPane.DEFAULT_LAYER);

        textoImagen.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        textoImagen.setText("Imagen cifrada usando HillMRIV");
        textoImagen.setBounds(428, 10, 190, 14);
        panelimagenes.add(textoImagen, javax.swing.JLayeredPane.DEFAULT_LAYER);

        textoImagenHill.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        textoImagenHill.setText("Imagen Original");
        textoImagenHill.setBounds(0, 10, 190, 14);
        panelimagenes.add(textoImagenHill, javax.swing.JLayeredPane.DEFAULT_LAYER);

        textoImagenHillMRIV.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        textoImagenHillMRIV.setText("Imagen cifrada usando Hill");
        textoImagenHillMRIV.setBounds(220, 10, 190, 14);
        panelimagenes.add(textoImagenHillMRIV, javax.swing.JLayeredPane.DEFAULT_LAYER);

        botonLimpiarImagenHillMRIV.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/cripto/gui/hmriv/images/reiniciar.png"))); // NOI18N
        botonLimpiarImagenHillMRIV.setToolTipText("Reiniciar Imagen");
        botonLimpiarImagenHillMRIV.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        botonLimpiarImagenHillMRIV.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                botonLimpiarImagenHillMRIVActionPerformed(evt);
            }
        });
        botonLimpiarImagenHillMRIV.setBounds(578, 230, 40, 40);
        panelimagenes.add(botonLimpiarImagenHillMRIV, javax.swing.JLayeredPane.DEFAULT_LAYER);

        botonGuardarImagenHillMRIV.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/cripto/gui/hmriv/images/guardar.png"))); // NOI18N
        botonGuardarImagenHillMRIV.setToolTipText("Guardar imagen");
        botonGuardarImagenHillMRIV.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        botonGuardarImagenHillMRIV.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                botonGuardarImagenHillMRIVActionPerformed(evt);
            }
        });
        botonGuardarImagenHillMRIV.setBounds(528, 230, 40, 40);
        panelimagenes.add(botonGuardarImagenHillMRIV, javax.swing.JLayeredPane.DEFAULT_LAYER);

        cargarImagenHillMRIV.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/cripto/gui/hmriv/images/stepIII.png"))); // NOI18N
        cargarImagenHillMRIV.setBounds(428, 30, 190, 190);
        panelimagenes.add(cargarImagenHillMRIV, javax.swing.JLayeredPane.DEFAULT_LAYER);

        cargarImagenHill.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/cripto/gui/hmriv/images/stepII.png"))); // NOI18N
        cargarImagenHill.setBounds(215, 30, 190, 190);
        panelimagenes.add(cargarImagenHill, javax.swing.JLayeredPane.DEFAULT_LAYER);

        botonLimpiarImagenHill.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/cripto/gui/hmriv/images/reiniciar.png"))); // NOI18N
        botonLimpiarImagenHill.setToolTipText("Reiniciar Imagen");
        botonLimpiarImagenHill.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        botonLimpiarImagenHill.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                botonLimpiarImagenHillActionPerformed(evt);
            }
        });
        botonLimpiarImagenHill.setBounds(365, 230, 40, 40);
        panelimagenes.add(botonLimpiarImagenHill, javax.swing.JLayeredPane.DEFAULT_LAYER);

        botonGuardarImagenHill.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/cripto/gui/hmriv/images/guardar.png"))); // NOI18N
        botonGuardarImagenHill.setToolTipText("Guardar imagen");
        botonGuardarImagenHill.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        botonGuardarImagenHill.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                botonGuardarImagenHillActionPerformed(evt);
            }
        });
        botonGuardarImagenHill.setBounds(315, 230, 40, 40);
        panelimagenes.add(botonGuardarImagenHill, javax.swing.JLayeredPane.DEFAULT_LAYER);

        botonLimpiarImagen.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/cripto/gui/hmriv/images/reiniciar.png"))); // NOI18N
        botonLimpiarImagen.setToolTipText("Reiniciar Imagen");
        botonLimpiarImagen.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        botonLimpiarImagen.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                botonLimpiarImagenActionPerformed(evt);
            }
        });
        botonLimpiarImagen.setBounds(150, 230, 40, 40);
        panelimagenes.add(botonLimpiarImagen, javax.swing.JLayeredPane.DEFAULT_LAYER);

        cargarImagen.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/cripto/gui/hmriv/images/stepI.png"))); // NOI18N
        cargarImagen.setToolTipText("Cargar una imagen");
        cargarImagen.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cargarImagenActionPerformed(evt);
            }
        });
        cargarImagen.setBounds(0, 30, 190, 190);
        panelimagenes.add(cargarImagen, javax.swing.JLayeredPane.DEFAULT_LAYER);

        botonGuardarImagen.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/cripto/gui/hmriv/images/guardar.png"))); // NOI18N
        botonGuardarImagen.setToolTipText("Guardar imagen");
        botonGuardarImagen.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        botonGuardarImagen.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                botonGuardarImagenActionPerformed(evt);
            }
        });
        botonGuardarImagen.setBounds(100, 230, 40, 40);
        panelimagenes.add(botonGuardarImagen, javax.swing.JLayeredPane.DEFAULT_LAYER);

        botonAbrirImagen.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/cripto/gui/hmriv/images/abrir.png"))); // NOI18N
        botonAbrirImagen.setToolTipText("Cargar una imagen");
        botonAbrirImagen.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        botonAbrirImagen.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                botonAbrirImagenActionPerformed(evt);
            }
        });
        botonAbrirImagen.setBounds(50, 230, 40, 40);
        panelimagenes.add(botonAbrirImagen, javax.swing.JLayeredPane.DEFAULT_LAYER);

        botonSalir.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/cripto/gui/hmriv/images/salir.png"))); // NOI18N
        botonSalir.setToolTipText("Salir");
        botonSalir.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                botonSalirActionPerformed(evt);
            }
        });

        botonAcercaDe.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/cripto/gui/hmriv/images/creditos.png"))); // NOI18N
        botonAcercaDe.setToolTipText("Acerca de..");
        botonAcercaDe.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        botonAcercaDe.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                botonAcercaDeActionPerformed(evt);
            }
        });

        jLabel1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/cripto/gui/hmriv/images/fondoTituloHillMRIV.png"))); // NOI18N

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(10, 10, 10)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(panelimagenes, javax.swing.GroupLayout.PREFERRED_SIZE, 620, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(panelClave, javax.swing.GroupLayout.PREFERRED_SIZE, 397, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(panelAcciones, javax.swing.GroupLayout.PREFERRED_SIZE, 220, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap())
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 489, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 25, Short.MAX_VALUE)
                .addComponent(botonAcercaDe, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(botonSalir, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(19, 19, 19))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGap(16, 16, 16)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addComponent(botonSalir, javax.swing.GroupLayout.PREFERRED_SIZE, 35, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(botonAcercaDe, javax.swing.GroupLayout.PREFERRED_SIZE, 35, javax.swing.GroupLayout.PREFERRED_SIZE)))
                    .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 55, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(panelimagenes, javax.swing.GroupLayout.PREFERRED_SIZE, 280, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(9, 9, 9)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(panelClave, javax.swing.GroupLayout.PREFERRED_SIZE, 146, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(panelAcciones, javax.swing.GroupLayout.PREFERRED_SIZE, 146, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void cleanImage(java.awt.event.ActionEvent evt) {
        botonLimpiarImagenHillMRIVActionPerformed(evt);
        botonLimpiarImagenHillActionPerformed(evt);
        botonLimpiarImagenActionPerformed(evt);
        cargarImagen.repaint();
        cargarImagen.updateUI();
        cargarImagenHill.repaint();
        cargarImagenHill.updateUI();
        cargarImagenHillMRIV.repaint();
        cargarImagenHillMRIV.updateUI();
    }

    private void cargarImagenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cargarImagenActionPerformed
        
        JFileChooser chooser = new JFileChooser();
        chooser.setAcceptAllFileFilterUsed(false);
        chooser.addChoosableFileFilter(new FileNameExtensionFilter("Mapa de bits(*.bmp, *.dib)", "bmp", "dib"));
        chooser.addChoosableFileFilter(new FileNameExtensionFilter("GIF(*.gif)", "gif"));
        chooser.addChoosableFileFilter(new FileNameExtensionFilter("PNG(*.png)", "png"));
        chooser.addChoosableFileFilter(new FileNameExtensionFilter("TIFF(*.tif, *.tiff)", "tif", "tiff"));
        chooser.addChoosableFileFilter(new FileNameExtensionFilter("JPEG(*.jpg, *.jpeg, *.jpe)", "jpg", "jpeg", "jpe"));
        chooser.showOpenDialog(this);
        File archivo = chooser.getSelectedFile();

        try {
            if (archivo.isFile()) {
                cleanImage(evt);
                String path = archivo.getAbsolutePath();

                int[][][] image = ImageProcessing.loadImageToRGB(path);
                int[][][] imageResize = ImageProcessing.resizeRGB(image, cargarImagen.getSize().width, cargarImagen.getSize().height);
                File directorio = new File("Images");
                directorio.mkdirs();

                ImageProcessing.saveImageFromRGB("Images\\Original.jpg", image);
                ImageProcessing.saveImageFromRGB("Images\\OriginalResize.jpg", imageResize);

                cargarImagen.setIcon(new javax.swing.ImageIcon(ImageProcessing.RGBImageToMarvinImage(imageResize).getBufferedImage()));
            }
        } catch (ArrayIndexOutOfBoundsException e) {
            JOptionPane.showMessageDialog(this, e.getMessage(), "Error al cifrar", JOptionPane.ERROR_MESSAGE);
        } catch (Exception e) {
            System.out.println("Carga de imagen cancelada");
        }
}//GEN-LAST:event_cargarImagenActionPerformed

    private void botonAbrirImagenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_botonAbrirImagenActionPerformed
        
        cargarImagenActionPerformed(evt);
    }//GEN-LAST:event_botonAbrirImagenActionPerformed

    private void botonCifrarHillActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_botonCifrarHillActionPerformed
        
        File p = new File("Images\\Original.jpg");
        if (p.exists()) {
            int[][][] image = ImageProcessing.loadImageToRGB("Images\\Original.jpg");
            try {

                Matrix key = loadKey();
                if (key != null) {
                    int[] encryptImageHill;
                    for (int x = 0; x < 3; x++) {
                        encryptImageHill = HillMRIVCipher.encryptHill(ArraysUtils.array2DTo1D(image[x]), key);
                        image[x] = ArraysUtils.array1DTo2D(encryptImageHill);
                    }
                    int[][][] imageResize = ImageProcessing.resizeRGB(image, 200, 200);
                    ImageProcessing.saveImageFromRGB("Images\\Hill.jpg", image);
                    ImageProcessing.saveImageFromRGB("Images\\HillResize.jpg", imageResize);
                    cargarImagenHill.setIcon(new javax.swing.ImageIcon(ImageProcessing.RGBImageToMarvinImage(imageResize).getBufferedImage()));
                } else {
                    System.out.println("Clave no encontrada");
                }
            } catch (NumberFormatException e) {
                JOptionPane.showMessageDialog(this, "El tamaño de clave ingresado es inválido, asegurese de ingresar un valor númerico:\n\n        Mayor a 3\n        Menor al tamaño de la imágen ( " + image[0].length + " )\n\n", "Error al cifrar", JOptionPane.ERROR_MESSAGE);
            }
        } else {
            JOptionPane.showMessageDialog(this, "No se ha cargado la imagen.\nAsegurese de especificar un archivo existente", "Error al cifrar", JOptionPane.ERROR_MESSAGE);
        }
    }//GEN-LAST:event_botonCifrarHillActionPerformed

    private void botonCifrarHillMRIVActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_botonCifrarHillMRIVActionPerformed
        
        File p = new File("Images\\Original.jpg");
        if (p.exists()) {
            int[][][] image = ImageProcessing.loadImageToRGB("Images\\Original.jpg");
            try {
                double[] iv = loadIV();
                System.out.print("IV");
                if (iv != null) {
                    int[] encryptImageHillMRIV;
                    Matrix key = loadKey();
                    if (key != null) {
                        for (int x = 0; x < 3; x++) {
                            encryptImageHillMRIV = HillMRIVCipher.encryptHillMRIV(ArraysUtils.array2DTo1D(image[x]), iv, key);
                            image[x] = ArraysUtils.array1DTo2D(encryptImageHillMRIV);
                        }
                        int[][][] imageResize = ImageProcessing.resizeRGB(image, 200, 200);
                        ImageProcessing.saveImageFromRGB("Images\\HillMRIV.jpg", image);
                        ImageProcessing.saveImageFromRGB("Images\\HillMRIVResize.jpg", imageResize);
                        cargarImagenHillMRIV.setIcon(new javax.swing.ImageIcon(ImageProcessing.RGBImageToMarvinImage(imageResize).getBufferedImage()));
                    } else {
                        System.out.println("Clave no encontrada");
                    }
                } else {
                    System.out.println("\nIV no encontrado");
                }
            } catch (NumberFormatException e) {
                JOptionPane.showMessageDialog(this, "El tamaño de clave ingresado es inválido, asegurese de ingresar un valor númerico:\n\n        Mayor a 0\n        Menor al tamaño de la imágen ( " + image[0].length + " )\n\n", "Error al cifrar", JOptionPane.ERROR_MESSAGE);
            }
        } else {
            JOptionPane.showMessageDialog(this, "No se ha cargado la imagen.\nAsegurese de especificar un archivo existente", "Error al cifrar", JOptionPane.ERROR_MESSAGE);
        }
    }//GEN-LAST:event_botonCifrarHillMRIVActionPerformed

    private void botonLimpiarImagenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_botonLimpiarImagenActionPerformed
        
        cargarImagen.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/cripto/gui/hmriv/images/stepI.png")));
        File p = new File("Images\\Original.jpg");
        if (p.exists()) {
            p.delete();
        }
        p = new File("Images\\OriginalResize.jpg");
        if (p.exists()) {
            p.delete();
        }

    }//GEN-LAST:event_botonLimpiarImagenActionPerformed

    private void botonLimpiarImagenHillActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_botonLimpiarImagenHillActionPerformed
        
        cargarImagenHill.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/cripto/gui/hmriv/images/stepII.png")));
        File p = new File("Images\\Hill.jpg");
        if (p.exists()) {
            p.delete();
        }
        p = new File("Images\\HillResize.jpg");
        if (p.exists()) {
            p.delete();
        }
    }//GEN-LAST:event_botonLimpiarImagenHillActionPerformed

    private void botonLimpiarImagenHillMRIVActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_botonLimpiarImagenHillMRIVActionPerformed
        
        cargarImagenHillMRIV.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/cripto/gui/hmriv/images/stepIII.png")));
        File p = new File("Images\\HillMRIV.jpg");
        if (p.exists()) {
            p.delete();
        }
        p = new File("Images\\HillMRIVResize.jpg");
        if (p.exists()) {
            p.delete();
        }
    }//GEN-LAST:event_botonLimpiarImagenHillMRIVActionPerformed

    private void botonGenerarClaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_botonGenerarClaveActionPerformed
        
        File imagenPrueba = new File("Images\\Original.jpg");
        if (imagenPrueba.exists()) {
            int[][][] image = ImageProcessing.loadImageToRGB("Images\\Original.jpg");
            try {
                int m = Integer.parseInt(tamanoClaveHillMRIV.getText());
                if (m > image[0][0].length || m < 4) {
                    JOptionPane.showMessageDialog(this, "El tamaño de clave ingresado es inválido, asegurese de ingresar un valor númerico:\n\n        Mayor a 3\n        Menor al tamaño de la imágen ( " + image[0].length + " )\n\n", "Error al cifrar", JOptionPane.ERROR_MESSAGE);
                } else {
                    String ruta = saveKey(generateKey(m).getArrayCopy(), generateIV(m));
                    cajaRutaArchivo.setText(ruta);
                }
            } catch (NumberFormatException e) {
                JOptionPane.showMessageDialog(this, "El tamaño de clave ingresado es inválido, asegurese de ingresar un valor númerico:\n\n        Mayor a 0\n        Menor al tamaño de la imágen ( " + image[0].length + " )\n\n", "Error al cifrar", JOptionPane.ERROR_MESSAGE);
            }
        } else {
            JOptionPane.showMessageDialog(this, "Asegurese de haber cargado una imagen\n\n", "Error al generar la clave", JOptionPane.ERROR_MESSAGE);
        }
    }//GEN-LAST:event_botonGenerarClaveActionPerformed

    private void botonVisualizarClaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_botonVisualizarClaveActionPerformed
        
        Runtime load = Runtime.getRuntime();

        try {
            if (cajaRutaArchivo.getText().length() < 3) {
                JOptionPane.showMessageDialog(this,
                        "Ocurrio un error al intentar visualizar el archivo: \n\n        Intente cargando o generando uno previamente\n\n",
                        "Error al visualizar el archivo de la clave", JOptionPane.ERROR_MESSAGE);
            } else {
                load.exec("notepad.exe " + cajaRutaArchivo.getText());
            }
        } catch (IOException ex) {
            Logger.getLogger(guiHillMRIV.class.getName()).log(Level.SEVERE, null, ex);
            JOptionPane.showMessageDialog(this, "Ocurrio un error al intentar visualizar el archivo: \n\n                 "
                    + "" + cajaRutaArchivo.getText() + "\n\nIntente abrirlo manualmente con su editor de texto preferido", "Error al visualizar el archivo de la clave", JOptionPane.ERROR_MESSAGE);
        }

    }//GEN-LAST:event_botonVisualizarClaveActionPerformed

    private void botonCargarClaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_botonCargarClaveActionPerformed
        
        
        JFileChooser chooser = new JFileChooser();
        chooser.addChoosableFileFilter(new TxTFilter());
        chooser.showOpenDialog(this);
        File archivo = chooser.getSelectedFile();
        try {
            cajaRutaArchivo.setText(archivo.getPath());
        } catch (Exception ex) {
            System.out.println("Carga cancelada");
        }
    }//GEN-LAST:event_botonCargarClaveActionPerformed

    private void botonGuardarImagenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_botonGuardarImagenActionPerformed
        
        File p = new File("Images\\Original.jpg");
        if (p.exists()) {
            JFileChooser chooser = new JFileChooser();
            chooser.addChoosableFileFilter(new FileNameExtensionFilter("*.jpg", "jpg"));
            chooser.showSaveDialog(this);
            File guardarEn = chooser.getSelectedFile();
            try {
                FileInputStream fis = new FileInputStream(p);
                FileOutputStream fos = new FileOutputStream(guardarEn.getPath().concat(".jpg"));
                FileChannel canalFuente = fis.getChannel();
                FileChannel canalDestino = fos.getChannel();
                canalFuente.transferTo(0, canalFuente.size(), canalDestino);
                fis.close();
                fos.close();
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(this, "Ocurrio un error al guardar la imagen.\nVerifique que el directorio destino sea válido.", "Error al guardar la imagen", JOptionPane.ERROR_MESSAGE);
            }
        } else {
            JOptionPane.showMessageDialog(this, "No hay imagen para guardar.\nAsegurese de cargar la imagen.", "Error al guardar la imagen", JOptionPane.ERROR_MESSAGE);
        }
    }//GEN-LAST:event_botonGuardarImagenActionPerformed

    private void botonGuardarImagenHillActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_botonGuardarImagenHillActionPerformed
        
        File p = new File("Images\\Hill.jpg");
        if (p.exists()) {
            JFileChooser chooser = new JFileChooser();
            chooser.addChoosableFileFilter(new FileNameExtensionFilter("*.jpg", "jpg"));
            chooser.showSaveDialog(this);
            File guardarEn = chooser.getSelectedFile();
            try {
                FileInputStream fis = new FileInputStream(p);
                FileOutputStream fos = new FileOutputStream(guardarEn.getPath().concat(".jpg"));
                FileChannel canalFuente = fis.getChannel();
                FileChannel canalDestino = fos.getChannel();
                canalFuente.transferTo(0, canalFuente.size(), canalDestino);
                fis.close();
                fos.close();
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(this, "Ocurrio un error al guardar la imagen.\nVerifique que el directorio destino sea válido.", "Error al guardar la imagen", JOptionPane.ERROR_MESSAGE);
            }
        } else {
            JOptionPane.showMessageDialog(this, "No hay imagen para guardar.\nAsegurese de cifrar la imagen original usando Hill.", "Error al guardar la imagen", JOptionPane.ERROR_MESSAGE);
        }
    }//GEN-LAST:event_botonGuardarImagenHillActionPerformed

    private void botonGuardarImagenHillMRIVActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_botonGuardarImagenHillMRIVActionPerformed
        File p = new File("Images\\HillMRIV.jpg");
        if (p.exists()) {
            JFileChooser chooser = new JFileChooser();
            chooser.addChoosableFileFilter(new FileNameExtensionFilter("*.jpg", "jpg"));
            chooser.showSaveDialog(this);
            File guardarEn = chooser.getSelectedFile();
            try {
                FileInputStream fis = new FileInputStream(p);
                FileOutputStream fos = new FileOutputStream(guardarEn.getPath().concat(".jpg"));
                FileChannel canalFuente = fis.getChannel();
                FileChannel canalDestino = fos.getChannel();
                canalFuente.transferTo(0, canalFuente.size(), canalDestino);
                fis.close();
                fos.close();
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(this, "Ocurrio un error al guardar la imagen.\nVerifique que el directorio destino sea válido.", "Error al guardar la imagen", JOptionPane.ERROR_MESSAGE);
            }
        } else {
            JOptionPane.showMessageDialog(this, "No hay imagen para guardar.\nAsegurese de cifrar la imagen original usando HillMRIV.", "Error al guardar la imagen", JOptionPane.ERROR_MESSAGE);
        }
    }//GEN-LAST:event_botonGuardarImagenHillMRIVActionPerformed

    private void botonSalirActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_botonSalirActionPerformed
        
        System.exit(0);
}//GEN-LAST:event_botonSalirActionPerformed

    private void botonAcercaDeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_botonAcercaDeActionPerformed
        
        JOptionPane.showMessageDialog(this,
                "Realizado por:\n"
                + "\nAgustín Moreno Cañadas - amorenoca@unal.edu.co"
                + "\nAlexis Irlande - airlande@unal.edu.co "
                + "\nDavid Montaño Fetecua - damontanofe@unal.edu.co"
                + "\nLaura Moreno Cubillos - lvmorenoc@unal.edu.co"
                + "\nChristian Rodríguez Bustos - carodriguezb@unal.edu.co\n"
                + "\nUniversidad Nacional de Colombia"
                + "\nSede Bogotá\n\n",
                "Acerca de...",
                JOptionPane.INFORMATION_MESSAGE);
}//GEN-LAST:event_botonAcercaDeActionPerformed
    private double[] loadIV() {

        double[] numeros = null;
        File archivo = new File(cajaRutaArchivo.getText());
        if (archivo.isFile()) {
            try {

                BufferedReader reader = new BufferedReader(new FileReader(archivo));
                Vector<String> cadenas = new Vector<String>();
                String linea;
                while ((linea = reader.readLine()) != null) {
                    cadenas.add(linea);
                }
                int m = Integer.parseInt(cadenas.get(0));
                numeros = new double[m];
                linea = cadenas.get(1);
                int n = 0;
                for (int y = 0; y < linea.length(); y++) {
                    int i = y;
                    while (Character.isDigit(linea.charAt(y))) {
                        y++;
                    }
                    if (i != y) {
                        numeros[n] = Double.parseDouble(linea.substring(i, y));
                        n++;
                    }
                }

            } catch (Exception ex) {
                System.out.println(ex.getMessage());
            }

        } else {
            JOptionPane.showMessageDialog(this, "No se ha cargado la clave.\nAsegurese de especificar un archivo existente. ", "Error al cifrar la imagen", JOptionPane.ERROR_MESSAGE);
        }
        return numeros;
    }

    private Matrix loadKey() {
        Matrix key = null;
        int[] numeros;
        File archivo = new File(cajaRutaArchivo.getText());
        if (archivo.isFile()) {
            try {

                BufferedReader reader = new BufferedReader(new FileReader(archivo));
                Vector<String> cadenas = new Vector<String>();
                String linea;
                while ((linea = reader.readLine()) != null) {
                    cadenas.add(linea);
                }
                int n = 0;
                int m = Integer.parseInt(cadenas.get(0));
                key = new Matrix(m, m);
                numeros = new int[m * m];

                for (int x = 2; x < cadenas.size(); x++) {
                    linea = cadenas.get(x);

                    for (int y = 0; y < linea.length(); y++) {
                        int i = y;
                        while (Character.isDigit(linea.charAt(y))) {
                            y++;
                        }
                        if (i != y) {
                            numeros[n] = Integer.parseInt(linea.substring(i, y));

                            n++;
                        }

                    }
                }
                int[][] keyInt = ArraysUtils.array1DTo2D(numeros);
                for (int x = 0; x < m; x++) {
                    for (int y = 0; y < m; y++) {
                        key.set(x, y, (double) keyInt[x][y]);
                    }
                }

            } catch (Exception ex) {
                System.out.println(ex.getMessage());
            }

        } else {
            JOptionPane.showMessageDialog(this, "Ruta de archivo inválida.\nAsegurese de especificar un archivo existente. ", "Error al cifrar la imagen", JOptionPane.ERROR_MESSAGE);
        }

        return key;
    }

    private String saveKey(double[][] key, double[] IV) {
        JFileChooser chooser = new JFileChooser();
        chooser.addChoosableFileFilter(new TxTFilter());
        chooser.showSaveDialog(this);
        File archivo = chooser.getSelectedFile();
        FileWriter fw = null;
        try {
            fw = new FileWriter(archivo);
            fw.write(key.length + "\n[");
            for (int x = 0; x < key.length; x++) {
                fw.write((int) IV[x] + " ");
            }
            fw.write("]\n");
            for (int x = 0; x < key.length; x++) {
                fw.write("[ ");
                for (int y = 0; y < key[0].length; y++) {
                    fw.write((int) key[x][y] + " ");
                }
                fw.write("]\n");
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fw != null) {
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                fw = null;
            }
        }
        return archivo.getAbsolutePath();
    }

    private static double[] generateIV(int m) {
        Random rnd = new Random();
        double[] iv = new double[m];
        for (int x = 0; x < m; x++) {
            iv[x] = rnd.nextInt(256);
        }
        return iv;
    }

    private static Matrix generateKey(int m) {
        Matrix key = new Matrix(m, m);
        Random rnd = new Random();
        double[][] keys = key.getArray();
        double[] av = new double[m];
        for (int x = 0; x < m; x++) {

            for (int y = 0; y < m; y++) {
                if (x == y) {
                    keys[x][y] = rnd.nextInt(256);
                } else {
                    keys[x][y] = 0;
                }

            }
        }

        return key;
    }

    public class TxTFilter extends javax.swing.filechooser.FileFilter {

        final static String txt = "txt";

        /** Creates a new instance of XMLFilter */
        public TxTFilter() {
        }

        public boolean accept(File f) {
            if (f.isDirectory()) {
                return true;
            }
            String s = f.getName();
            int i = s.lastIndexOf('.');

            if (i > 0 && i < s.length() - 1) {
                String extension = s.substring(i + 1).toLowerCase();
                if (txt.equals(extension)) {
                    return true;
                } else {
                    return false;
                }
            }
            return false;
        }

        public String getDescription() {
            return "archivos .txt";
        }
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {

        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                try {
                    UIManager.setLookAndFeel("org.pushingpixels.substance.api.skin.SubstanceBusinessBlackSteelLookAndFeel");
                } catch (Exception e) {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException ex) {
                        Logger.getLogger(guiHillMRIV.class.getName()).log(Level.SEVERE, null, ex);
                    } catch (InstantiationException ex) {
                        Logger.getLogger(guiHillMRIV.class.getName()).log(Level.SEVERE, null, ex);
                    } catch (IllegalAccessException ex) {
                        Logger.getLogger(guiHillMRIV.class.getName()).log(Level.SEVERE, null, ex);
                    } catch (UnsupportedLookAndFeelException ex) {
                        Logger.getLogger(guiHillMRIV.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
                new guiHillMRIV().setVisible(true);
            }
        });

    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton botonAbrirImagen;
    private javax.swing.JButton botonAcercaDe;
    private javax.swing.JButton botonCargarClave;
    private javax.swing.JButton botonCifrarHill;
    private javax.swing.JButton botonCifrarHillMRIV;
    private javax.swing.JButton botonGenerarClave;
    private javax.swing.JButton botonGuardarImagen;
    private javax.swing.JButton botonGuardarImagenHill;
    private javax.swing.JButton botonGuardarImagenHillMRIV;
    private javax.swing.JButton botonLimpiarImagen;
    private javax.swing.JButton botonLimpiarImagenHill;
    private javax.swing.JButton botonLimpiarImagenHillMRIV;
    private javax.swing.JButton botonSalir;
    private javax.swing.JButton botonVisualizarClave;
    private javax.swing.JTextField cajaRutaArchivo;
    private javax.swing.JButton cargarImagen;
    private javax.swing.JButton cargarImagenHill;
    private javax.swing.JButton cargarImagenHillMRIV;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLayeredPane panelAcciones;
    private javax.swing.JLayeredPane panelClave;
    private javax.swing.JLayeredPane panelimagenes;
    private javax.swing.JTextField tamanoClaveHillMRIV;
    private javax.swing.JLabel textoImagen;
    private javax.swing.JLabel textoImagenHill;
    private javax.swing.JLabel textoImagenHillMRIV;
    private javax.swing.JLabel textoRuta;
    private javax.swing.JLabel textoTamanoclave;
    // End of variables declaration//GEN-END:variables
}
